# LuckPay Web Manage System
#
# Copyright (c) 2016 Lucky Byte, Inc.
#
express = require 'express'
pgsql   = require 'pg'
crypto  = require 'crypto'
moment  = require 'moment'
sendmail = require '../lib/sendmail'
router = express.Router()
module.exports = router

# 登陆页面
router.get '/', (req, res, next) ->
    # 如果用户已经登录了，则访问登录页面是没有意义的
    if req.session.userinfo and req.session.userinfo.uuid
        return res.redirect '/'

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    # 自动解锁所有需要解锁的用户
    await client.query "update web_users set
        disabled = false, failed_cnt = 0, unlock_time = null
        where unlock_time is not null and
            unlock_time < CURRENT_TIMESTAMP", defer err, result
    if err then done(client); return next(err)
    done()
    res.render 'login'


# 处理登陆表单提交
router.post '/', (req, res, next) ->
    if not req.body.username or not req.body.password
        res.locals.echo_title = '登陆失败'
        res.locals.echo_message = '用户名和密码不能为空，请重新登陆'
        res.render 'login'

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    # 通过用户名查询匹配的数据库记录
    await client.query "select u.*,
            r.name as role_name, r.root as role_root,
            r.permission as permission
        from web_users as u left join web_roles as r on u.role = r.uuid
        where u.loginname = $1", [
            req.body.username
        ], defer err, result
    if err then done(client); return next(err)

    # 如果查询结果为空，继续检查是否系统没有任何用户，在没有用户的情况下，
    # 可以通过默认的用户 root 登录
    if result.rows.length < 1
        await client.query "select count(*) as count from web_users", defer err, result
        if err then done(client); return next(err)
        done()
        if parseInt(result.rows[0].count) == 0
            if req.body.username == 'root' and req.body.password == 'root'
                req.session.userinfo =
                    serial: 0,
                    uuid: 'uuid',
                    loginname: 'root',
                    realname: '系统用户',
                    role_name: 'root',
                    role_root: true,
                    permission: {},
                return req.session.save (err) -> res.redirect '/'
        # 如果系统用户不为空，则返回用户名无效的错误
        res.locals.echo_title = '登陆失败'
        return res.render 'login', echo_message: '用户名错误，请确认后重新登陆'

    user = result.rows[0]

    # 检查用户是否已被禁用
    if user.disabled
        done()
        res.locals.echo_title = '登陆失败'
        return res.render 'login', echo_message: '该用户已被禁用，不允许登录...'

    # 比对用户密码
    sha1 = crypto.createHash 'sha1'
    sha1.update(user.uuid)
    password = sha1.update(req.body.password.trim()).digest('hex')
    if password != user.password
        if not user.lock_enable
            res.locals.echo_title = '登录失败'
            res.locals.echo_message = '密码错误，请重新登录'
            return res.render 'login'

        # 如果连续失败达到一定的次数，则用户在接下来一段时间内不允许登录
        if user.failed_cnt >= 4
            unlock_time = moment().add(5, 'minutes')
            console.log unlock_time
            await client.query "update web_users set
                disabled = true, unlock_time = $1 where uuid = $2", [
                    unlock_time, user.uuid
                ], defer err, result
            done()
            res.locals.echo_title = '密码错误，登录失败'
            res.locals.echo_message = '用户被锁定，您可以等待 5 分钟后自动解锁，或联系管理员帮助解锁'
            res.locals.locked = true
            res.locals.wait_time = 5 * 60
            return res.render 'login'
        else
            # 增加用户登录失败次数
            await client.query "update web_users set
                failed_cnt = failed_cnt + 1 where uuid = $1", [
                    user.uuid
                ], defer err, result
            done()
            res.locals.echo_title = '密码错误，登录失败'
            res.locals.echo_message = "您已连续登录失败 #{user.failed_cnt + 1} 次，" +
                "还剩 #{4 - user.failed_cnt} 次尝试机会"
            res.locals.retry_cnt = 4 - user.failed_cnt
            return res.render 'login'

    # 登录成功后将失败次数清空
    await client.query "update web_users set
        failed_cnt = 0, unlock_time = null where uuid = $1", [
            user.uuid
        ], defer err, result

    # 记录登录历史
    await client.query "insert into web_login (
            login_user, remote_ip, notes
        ) values (
            $1, $2, $3
        )", [
            user.uuid, req.ip, "#{user.realname} 登录成功"
        ], defer err, result

    # 如果域名是 lucky-byte.com，则 demo 用户登录时给管理员发送一封邮件
    if req.hostname is 'lucky-byte.com' and user.loginname is 'demo'
        content = """
            <p>登录时间: #{moment().format('MM-DD HH:mm:ss')}.</p>
            <p>登录地址: #{req.ip}</p>
        """
        sendmail
            subject: 'DEMO 用户登录'
            to: 'xiaohu xiaohu@lucky-byte.com'
            html: content

    # 会话信息
    req.session.userinfo = user
    req.session.userinfo.password = null
    if not req.session.userinfo.permission
        req.session.userinfo.permission = {}

    # 如果之前有此用户登录，则将其退出
    await client.query "delete from web_session
        where sess#>>'{userinfo, uuid}' = $1", [
            req.session.userinfo.uuid
        ], defer err, result
    if err then done(client); return next(err)
    done()

    # 重定向之前必须先保存会话
    req.session.save (err) ->
        if err then return res.render 'login',
            echo_message: '保存会话数据失败，请联系系统管理员'

        # 跳转到用户最后希望访问的页面
        last_access = req.session.last_access or '/'
        delete req.session.last_access
        res.redirect last_access
